/**
 * Copyright (c) 2005-2010 springside.org.cn
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * 
 * $Id: ReflectionUtils.java 1211 2010-09-10 16:20:45Z calvinxiu $
 */
package com.cow.framework.utils.reflection;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * 
 * 反射工具类.
 *  
 * @author hehzh
 * @since 2014-10-16
 * @version 1.0
 *
 */
public class ReflectionUtils {
	// private static Field getAccessibleField(final Object obj,
	// final String fieldName) {
	// Assert.notNull(obj, "object不能为空");
	// Assert.hasText(fieldName, "fieldName");
	// for (Class<?> superClass = obj.getClass(); superClass != Object.class;
	// superClass = superClass
	// .getSuperclass()) {
	// try {
	// Field field = superClass.getDeclaredField(fieldName);
	// field.setAccessible(true);
	// return field;
	// } catch (NoSuchFieldException e) {// NOSONAR
	// // Field不在当前类定义,继续向上转型
	// }
	// }
	// return null;
	// }
	//
	// /**
	// * 直接调用对象方法, 无视private/protected修饰符. 用于一次性调用的情况.
	// */
	// private static Object invokeMethod(final Object obj,
	// final String methodName, final Class<?>[] parameterTypes,
	// final Object[] args) {
	// Method method = getAccessibleMethod(obj, methodName, parameterTypes);
	// if (method == null) {
	// throw new IllegalArgumentException("Could not find method ["
	// + methodName + "] on target [" + obj + "]");
	// }
	//
	// try {
	// return method.invoke(obj, args);
	// } catch (Exception e) {
	// throw convertReflectionExceptionToUnchecked(e);
	// }
	// }
	//
	// /**
	// * 循环向上转型, 获取对象的DeclaredMethod,并强制设置为可访问. 如向上转型到Object仍无法找到, 返回null.
	// 用于方法需要被多次调用的情况.
	// * 先使用本函数先取得Method,然后调用Method.invoke(Object obj, Object... args)
	// */
	// private static Method getAccessibleMethod(final Object obj,
	// final String methodName, final Class<?>... parameterTypes) {
	// Assert.notNull(obj, "object不能为空");
	//
	// for (Class<?> superClass = obj.getClass(); superClass != Object.class;
	// superClass = superClass
	// .getSuperclass()) {
	// try {
	// Method method = superClass.getDeclaredMethod(methodName,
	// parameterTypes);
	//
	// method.setAccessible(true);
	//
	// return method;
	//
	// } catch (NoSuchMethodException e) {// NOSONAR
	// // Method不在当前类定义,继续向上转型
	// }
	// }
	// return null;
	// }

	/**
	 * 获得clazz的父类的第一个泛型参数的类型<br>
	 * 例如clazz是UserDao,它的定义是public UserDao extends HibernateDao<User,Long>),则函数返回值User<br>
	 * 示例：Class  entityClass = ReflectionUtils.getSuperClassGenricType(UserDao.getClass());<br>
	 * 
	 * @param clazz 类
	 * @return 父类的第一个泛型参数的类型<br>
	 * 如无法找到, 返回Object.class<br>
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	public static <T> Class<T> getSuperClassGenricType(final Class clazz) {
		return getSuperClassGenricType(clazz, 0);
	}

	/**
	 * 获得clazz的父类的某个泛型参数的类型<br>
	 * 例如clazz是UserDao,它的定义是public UserDao extends HibernateDao<User,Long>),则函数返回值User<br>
	 * 示例：Class  entityClass = ReflectionUtils.getSuperClassGenricType(UserDao.getClass(),1);<br>
	 * 
	 * @param clazz 类
	 * @param index 指定取第几个泛型参数,从0开始
	 * @return 父类的某个泛型参数的类型<br>
	 * 如无法找到, 返回Object.class<br>
	 */
	@SuppressWarnings("rawtypes")
	public static Class getSuperClassGenricType(final Class clazz, final int index) {

		Type genType = clazz.getGenericSuperclass();

		if (!(genType instanceof ParameterizedType)) {
			return Object.class;
		}

		Type[] params = ((ParameterizedType) genType).getActualTypeArguments();

		if (index >= params.length || index < 0) {
			return Object.class;
		}
		if (!(params[index] instanceof Class)) {
			return Object.class;
		}
		return (Class) params[index];
	}

	/**
	 * 
	 * 将反射时的checked exception转换为unchecked exception.
	 * 
	 * @param e 输入exception
	 * @return 转换后的exception
	 *
	 */
	public static RuntimeException convertReflectionExceptionToUnchecked(Exception e) {
		if (e instanceof IllegalAccessException || e instanceof IllegalArgumentException
				|| e instanceof NoSuchMethodException) {
			return new IllegalArgumentException("Reflection Exception.", e);
		} else if (e instanceof InvocationTargetException) {
			return new RuntimeException("Reflection Exception.", ((InvocationTargetException) e).getTargetException());
		} else if (e instanceof RuntimeException) {
			return (RuntimeException) e;
		}
		return new RuntimeException("Unexpected Checked Exception.", e);
	}
}
